package it.polito.connectedcar.message;

import it.polito.connectedcar.tcc.zone.Token;
import it.polito.connectedcar.vehicle.VehicleNeighborhood;
import it.polito.connectedcar.vehicle.VehicleZone;

import java.net.InetSocketAddress;
import java.util.concurrent.BlockingQueue;

/**
 * This class is similar to {@link TCCMessageProcessor} in a sense that is used
 * to decouple the message receiving of network level and the message processing
 * of higher level. In this intermediate level , messages coming from lower
 * levels by being inserted into the queue , are validated and possibly dropped
 * or passed to registered listeners in order to be further analyzed
 * 
 * @author Nicola Aresta
 * 
 */
public class VehicleMessageProcessor extends Thread {

	private BlockingQueue<VehicleFromVehicleMessage> vehicleMessageQueue;
	private VehicleNeighborhood vehicleNeighborhood;
	private VehicleMessageListener vehicleMessageListener;

	private volatile boolean canRun;

	public VehicleMessageProcessor(VehicleNeighborhood vehicleNeighborhood,MessageQueueFactory messageQueueFactory) {
		vehicleMessageQueue = messageQueueFactory.getVehiclesMessageQueue();
		this.vehicleNeighborhood = vehicleNeighborhood;
		canRun = true;
	}

	@Override
	public void run() {
		while (canRun) {
			try {
				VehicleFromVehicleMessage m = vehicleMessageQueue.take();
				InetSocketAddress is = m.getSourceAddress();
				Token t = null;
				for (VehicleZone zone : vehicleNeighborhood.getNeighbors()) {
					for (InetSocketAddress address : zone.getVehicles()) {
						if (address.equals(is)) {
							t = zone.getZoneToken();
							break;
						}
					}
				}

				try {
					if (t != null && m.processMessage(t) && vehicleMessageListener != null)
						vehicleMessageListener.onMessageReceived(m);

				} catch (Exception e) {
					e.printStackTrace();
				}
				/*
				 * using the token t , recalculate the digest on the message
				 * payload:
				 */

				/*
				 * 1) verify authenticity and integrity 2) extract all records
				 * and verify authorization of all records 3) apply intelligence
				 * on data 4) operates on Vehicle info
				 */

			} catch (InterruptedException e) {
				e.printStackTrace();
			}

		}
	}

	public void askStop() {
		this.canRun = false;
	}

	public VehicleMessageListener getVehicleMessageListener() {
		return vehicleMessageListener;
	}

	public void setVehicleMessageListener(
			VehicleMessageListener vehicleMessageListener) {
		this.vehicleMessageListener = vehicleMessageListener;
	}

}
